package com.yycx.msg.provider.service.impl;

import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.util.TypeUtils;
import com.yycx.common.base.client.BasePushClient;
import com.yycx.common.base.service.BaseAdminUserService;
import com.yycx.common.base.vo.MsgSendRequest;
import com.yycx.common.constants.CommonConstants;
import com.yycx.common.mybatis.base.service.impl.BaseServiceImpl;
import com.yycx.common.base.entity.EntityMap;
import com.yycx.common.mybatis.interceptor.ExportInterceptor;
import com.yycx.common.mybatis.model.ResultBody;
import com.yycx.common.mybatis.query.CriteriaDelete;
import com.yycx.common.mybatis.query.CriteriaQuery;
import com.yycx.common.mybatis.query.CriteriaSave;
import com.yycx.common.mybatis.query.CriteriaUpdate;
import com.yycx.common.security.OpenHelper;
import com.yycx.common.utils.ApiAssert;
import com.yycx.common.utils.DateUtils;
import com.yycx.common.base.utils.FlymeUtils;
import com.yycx.common.utils.SpringContextHolder;
import com.yycx.common.utils.StringUtils;
import com.yycx.module.admin.client.entity.BaseUser;
import com.yycx.module.admin.provider.mapper.BaseUserCompanyMapper;
import com.yycx.module.admin.provider.service.BaseUserService;
import com.yycx.msg.client.entity.MsgContent;
import com.yycx.msg.client.entity.MsgType;
import com.yycx.msg.client.enums.MsgTypeEnum;
import com.yycx.msg.provider.handler.SendMsgHandler;
import com.yycx.msg.provider.mapper.MsgContentMapper;
import com.yycx.msg.provider.service.MsgContentService;
import com.yycx.msg.provider.service.MsgReceiveService;
import com.yycx.msg.provider.service.MsgTypeService;
import com.yycx.msg.provider.websocket.WebSocketServerEndpoint;
import javassist.bytecode.analysis.Type;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 消息表接口实现类
 *
 * @author flyme
 * @date 2020-02-26
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class MsgContentServiceImpl extends BaseServiceImpl<MsgContentMapper, MsgContent> implements MsgContentService {

    @Resource
    private MsgContentMapper msgContentMapper;

    @Autowired(required = false)
    private BasePushClient basePushClient;

    @Resource
    private MsgReceiveService msgReceiveService;

    @Autowired
    private BaseUserService baseUserService;

    @Autowired
    private MsgTypeService msgTypeService;


    @Override
    public ResultBody beforeEdit(CriteriaUpdate<MsgContent> cu, MsgContent msgContent, EntityMap extra) {
       /* String msgSummary = StringUtils.stripXss(msgContent.getMsgContent()).trim();
        if (FlymeUtils.isNotEmpty(msgSummary) && msgSummary.length() > 20) {
            //msgSummary = msgSummary.substring(0, 18);
        }
        //msgContent.setMsgSummary(msgSummary);*/
        return super.beforeEdit(cu, msgContent, extra);
    }

    @Override
    public ResultBody beforeAdd(CriteriaSave cs, MsgContent content, EntityMap extra) {
        content.setDeleted(CommonConstants.DEL_NO);
        //未发布
        content.setMsgState(CommonConstants.DISABLED);
        String msgSummary = StringUtils.stripXss(content.getMsgContent()).trim();
        if (FlymeUtils.isNotEmpty(msgSummary) && msgSummary.length() > 20) {
            msgSummary = msgSummary.substring(0, 18);
        }
        //未推送
        content.setPushState(CommonConstants.DISABLED);
        content.setSendTime(DateUtils.getNowDate());
        content.setMsgSummary(msgSummary);
        return ResultBody.ok();
    }

    @Override
    public ResultBody afterAdd(CriteriaSave cs, MsgContent msgContent, EntityMap extra) {
        return super.afterAdd(cs, msgContent, extra);
    }


    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public ResultBody beforePageList(CriteriaQuery<MsgContent> cq, MsgContent content, EntityMap requestMap) {
        cq.addSelect(MsgType.class, "typeName");
        cq.addSelect(MsgContent.class, "*");
        cq.like(MsgContent.class, "msgTitle");
        cq.and(i -> i.eq("typeCode", MsgTypeEnum.SysMsg.getCode()));
        cq.orderByDesc("content.createTime");
        cq.createJoin(MsgType.class);
        return ResultBody.ok();
    }

    @Override
    public ResultBody afterDelete(CriteriaDelete cd, Serializable[] ids) {
        msgReceiveService.deleteByMsgId(ids);
        return super.afterDelete(cd, ids);
    }

    @Override
    public List<MsgContent> selectNotReceiveByUserId(EntityMap params) {
        return msgContentMapper.selectNotReceiveByUserId(params);
    }

    @Override
    public ResultBody sendMessage(Map params) {
        try {
            Long msgId = MapUtil.getLong(params, "msgId");
            MsgContent msgContent = getById(msgId);
            String handlerName = (String) params.get("handlerName");
            if (FlymeUtils.isNotEmpty(handlerName)) {
                SendMsgHandler handler = SpringContextHolder.getHandler(handlerName, SendMsgHandler.class);
                handler.sendMsg(msgContent);
            }
            msgContent.setMsgState(CommonConstants.ENABLED);
            updateById(msgContent);
        } catch (Exception e) {
            return ResultBody.ok("发布失败");
        }
        return ResultBody.ok("发布成功");
    }

    @Override
    public ResultBody pushMessage(Map params) {
        Long msgId = MapUtil.getLong(params, "msgId");
        try {
            MsgContent msgContent = getById(msgId);
            if (FlymeUtils.isNotEmpty(basePushClient)) {
                //推送名称
                String msg_push_name = redisUtils.getConfig("msg_push_name");
                if (FlymeUtils.isNotEmpty(msg_push_name)) {
                    Integer deviceType = FlymeUtils.getInteger(msgContent.getPushDeviceType(), 0);
                    String title = msgContent.getMsgTitle();
                    basePushClient.getService(msg_push_name).sendByDeviceType(deviceType, "系统通知", title, title, null);
                    msgContent.setPushState(CommonConstants.ENABLED);
                    updateById(msgContent);
                } else {
                    return ResultBody.failed("未配置推送名称");
                }
            } else {
                return ResultBody.failed("推送客户端未配置");
            }
        } catch (Exception e) {
            return ResultBody.ok("推送失败");
        }
        return ResultBody.ok("推送成功");
    }

    @Override
    public List<EntityMap> selectMsgContentByTypeCode(String typeCode, Integer limit) {
        CriteriaQuery<MsgContent> cq = new CriteriaQuery<>(MsgContent.class);
        cq.addSelect(MsgType.class, "typeName");
        cq.addSelect(MsgContent.class, "*");
        cq.eq(true, "typeCode", typeCode);
        cq.eq("msgState", 1);
        cq.orderByDesc("content.createTime");
        if (limit > 0) {
            cq.last("limit " + limit);
        }
        cq.createJoin(MsgType.class);
        return selectEntityMap(cq);
    }

    @Override
    public Long totalMsgByType(Map params) {
        Long msgCount = 0L;
        String typeCode = MapUtil.getStr(params, "typeCode");
        MsgType msgType = msgTypeService.findByTypeCode(typeCode);
        if (FlymeUtils.isNotEmpty(msgType)) {
            CriteriaQuery<MsgContent> cq = new CriteriaQuery<>(MsgContent.class);
            cq.eq(true, "msgTypeId", msgType.getMsgTypeId());
            msgCount = count(cq);
        }
        return msgCount;
    }

    /**
     * 根据类型和用户删除消息
     *
     * @param msgTypeId
     * @param userId
     */
    public void deleteUserMsgByTypeId(Long userId, Integer msgTypeId) {
        CriteriaDelete cd = new CriteriaDelete();
        cd.eq(true, "msgTypeId", msgTypeId);
        cd.eq(true, "receiveConfig", userId);
        remove(cd);
    }


    /**
     * 发送并推送消息
     *
     * @param msgSendRequest
     * @return
     */
    public MsgContent sendMessage(MsgSendRequest msgSendRequest) {
        String typeCode = msgSendRequest.getTypeCode();
        ApiAssert.isNotEmpty("消息类型不能为空", typeCode);
        MsgType msgType = msgTypeService.findByTypeCode(typeCode);
        if (FlymeUtils.isNotEmpty(msgType)) {
            String title = msgSendRequest.getTitle();
            MsgContent msgContent = new MsgContent();
            Object receiveConfig = msgSendRequest.getReceiveConfig();
            msgContent.setMsgTitle(title);
            msgContent.setMsgTypeId(msgType.getMsgTypeId());
            msgContent.setMsgState(CommonConstants.ENABLED);
            msgContent.setDeleted(CommonConstants.DEL_NO);
            msgContent.setMsgContent(msgSendRequest.getContent());
            msgContent.setUserId(msgSendRequest.getSendUserId());
            msgContent.setSendTime(DateUtils.getNowDateTime());
            msgContent.setPushState(CommonConstants.ENABLED);
            if (FlymeUtils.isNotEmpty(receiveConfig)) {
                msgContent.setReceiveConfig(receiveConfig.toString());
            }
            boolean result = save(msgContent);
            if (result) {
                //推送服务名称
                String msg_push_name = redisUtils.getConfig("msg_push_name");
                boolean push = FlymeUtils.getBoolean(msgSendRequest.getPush(), false);
                if (FlymeUtils.isNotEmpty(msg_push_name) && push) {
                    basePushClient.getService(msg_push_name).pushMessage(msgSendRequest);
                }
            }
            return msgContent;
        }
        return null;
    }
}
